package cn.edu.sjtu.se.dslab.controller;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import cn.edu.sjtu.se.dslab.component.aadl.AADLModel;
import cn.edu.sjtu.se.dslab.component.aadl.AADLParser;
import cn.edu.sjtu.se.dslab.component.data.AvionicsEquipment;
import cn.edu.sjtu.se.dslab.component.data.DomainEntity;
import cn.edu.sjtu.se.dslab.component.design.DesignPattern;
import cn.edu.sjtu.se.dslab.component.design.DesignPatternComponent;
import cn.edu.sjtu.se.dslab.component.design.DesignPatternType;
import cn.edu.sjtu.se.dslab.component.dp.parse.DesignPatternInstanceBean;
import cn.edu.sjtu.se.dslab.component.dp.parse.Property;
import cn.edu.sjtu.se.dslab.component.method.ComponentInterface;
import cn.edu.sjtu.se.dslab.component.method.InterfaceMethod;
import cn.edu.sjtu.se.dslab.component.method.util.MethodComponentLink;
import cn.edu.sjtu.se.dslab.component.method.util.MethodComponentTool;
import cn.edu.sjtu.se.dslab.project.BusZone;
import cn.edu.sjtu.se.dslab.project.DisplayZone;
import cn.edu.sjtu.se.dslab.project.EntityZone;
import cn.edu.sjtu.se.dslab.project.Project;
import cn.edu.sjtu.se.dslab.service.IAvionicsEquipmentService;
import cn.edu.sjtu.se.dslab.service.IBusZoneService;
import cn.edu.sjtu.se.dslab.service.IButtonService;
import cn.edu.sjtu.se.dslab.service.IDesignPatternComponentService;
import cn.edu.sjtu.se.dslab.service.IDesignPatternService;
import cn.edu.sjtu.se.dslab.service.IDisplayZoneService;
import cn.edu.sjtu.se.dslab.service.IDomainEntityService;
import cn.edu.sjtu.se.dslab.service.IEntityZoneService;
import cn.edu.sjtu.se.dslab.service.IEquipmentCategoryService;
import cn.edu.sjtu.se.dslab.service.IInterfaceMethodService;
import cn.edu.sjtu.se.dslab.service.IMethodComponentService;
import cn.edu.sjtu.se.dslab.service.IPositionService;
import cn.edu.sjtu.se.dslab.service.IProjectService;
import cn.edu.sjtu.se.dslab.service.IUserService;
import cn.edu.sjtu.se.dslab.service.IVariableService;
import cn.edu.sjtu.se.dslab.util.Const;
import cn.edu.sjtu.se.dslab.util.FileUtil;

@Controller
@RequestMapping(value = "/project")
public class DesignPatternComponentController {

	private static final Logger logger = Logger
			.getLogger(DesignPatternComponentController.class);
	
	@Resource(name = "entityZoneService")
	IEntityZoneService entityZoneService;
	
	@Resource(name = "busZoneService")
	IBusZoneService busZoneService;

	@Resource(name = "designPatternComponentService")
	IDesignPatternComponentService designPatternComponentService;

	@Resource(name = "designPatternService")
	IDesignPatternService designPatternService;

	@Resource(name = "userService")
	IUserService userService;

	@Resource(name = "domainEntityService")
	IDomainEntityService domainEntityService;

	@Resource(name = "avionicsEquipmentService")
	IAvionicsEquipmentService avionicsEquipmentService;

	@Resource(name = "equipmentCategoryService")
	IEquipmentCategoryService equipmentCategoryService;

	@Resource(name = "interfaceMethodService")
	IInterfaceMethodService interfaceMethodService;

	// @Resource(name="busDpCodeGenerator")
	// DesignPatternCodeGenerator codeGenerator;

	@Resource(name = "methodComponentTool")
	MethodComponentTool methodComponentTool;

	@Resource(name = "methodComponentService")
	IMethodComponentService methodComponentService;

	@Resource(name = "projectService")
	IProjectService projectService;

	@Resource(name = "aadlParser")
	AADLParser aadlParser;

	@Resource(name = "buttonService")
	IButtonService buttonService;
	
	@Resource(name = "displayZoneService")
	IDisplayZoneService displayZoneService;
	
	@Resource(name="positionService")
	IPositionService positionService;
	
	@Resource(name="variableService")
	IVariableService variableService;

	@RequestMapping(value = "/design_pattern_component", method = RequestMethod.GET)
	public ModelAndView getDesignPatternComponentList(
			@RequestParam(value = "PageNum", defaultValue = "1") int pageNum) {
		ModelAndView mav = new ModelAndView();
		mav.setViewName("design_pattern_component");

		List<DesignPattern> dpList = designPatternService
				.getDesignPatternList();
		mav.addObject("designPatternList", dpList);

		List<DesignPatternComponent> dpcList = designPatternComponentService
				.getDesignPatternComponentList();
		mav.addObject("designPatternComponentList", dpcList);

		return mav;
	}

	@RequestMapping(value = "/design_pattern_component/{symbal}", method = RequestMethod.GET)
	public ModelAndView getDesignPatternComponent(
			@PathVariable(value = "symbal") String symbal,
			@RequestParam(value = "PageNum", defaultValue = "1") int pgNo) {
		ModelAndView mav = new ModelAndView();
		mav.setViewName("design_pattern_component");

		List<DesignPattern> dpList = designPatternService
				.getDesignPatternList();
		mav.addObject("designPatternList", dpList);

		List<DesignPatternComponent> dpcList = designPatternComponentService
				.getDesignPatternComponentsByDP(pgNo, Const.PAGESIZE, symbal);
		for (DesignPatternComponent dpc : dpcList) {
			System.out.println(dpc.getCreateTime());
		}
		// 用symbal查找对应的的设计模式
		DesignPattern dp = designPatternService
				.getDesignPatternByType(DesignPatternType.valueOf(symbal));
		mav.addObject("designPatternName", dp.getName());
		// try {
		// dpName = new String(dpName.getBytes("ISO8859_1"),"utf-8");
		// } catch (UnsupportedEncodingException e) {
		// dpName = "";
		// }
		// mav.addObject("designPatternName", dpName);

		mav.addObject("designPatternComponentList", dpcList);

		mav.addObject("designPatternUri", dp.getUri());
		

		return mav;
	}

	// @RequestMapping(value="/design_pattern_component/add", method =
	// RequestMethod.POST)
	// public String addDesignPatternComponent(DesignPatternComponent
	// dpComponent,
	// @RequestParam String name, @RequestParam String designPatternUri){
	//
	// User user = userService.getUserById(3);//还要改
	// DesignPattern dp =
	// designPatternService.getDesignPatternByUri(designPatternUri);
	// DesignPatternInstance dpi = new DesignPatternInstance();
	// dpi.setName(name);
	// dpi.setDesignPattern(dp);
	// dpi.setComponent(dpComponent);
	// dpComponent.setInstance(dpi);
	// dpComponent.setOwner(user);
	// dpComponent.setXmlPath(dp.getSymbal() + "/" + dpComponent.getXmlPath());
	// //把xml路径变成bus/file.xml
	// designPatternComponentService.addDesignPatternComponent(dpComponent);
	//
	// return new
	// StringBuffer("redirect:").append(dp.getSymbal()).append("/").append(dp.getName()).toString();
	// }

	/**
	 * @Title: addFourDesignPatternComponent
	 * @Description: create four design pattern component for the project and
	 *               save it in the project directory
	 * @param projectId
	 *            the id of the project
	 * @return String the corresponding page name
	 */
	@RequestMapping(value = "/design_pattern_component/{projectId}/edit")
	public String editDesignPatternComponent(@RequestParam long projectId,
			@RequestParam String type) {
		String dpcUri = designPatternComponentService
				.getDesignPatternCommponentByType(projectId,
						DesignPatternType.valueOf(type.toUpperCase())).getUri();
		return "redirect:../../" + dpcUri.replace(':', '/') + "?projectId="
				+ projectId;
	}

	// ??
//	@RequestMapping(value = "/design_pattern_component/{type}/{uri}", method = RequestMethod.GET)
	@RequestMapping(value = "/{projectId}/design_pattern_component/{type}/{operation}", method = RequestMethod.GET)
	public ModelAndView getDesignPatternComponent(
			@PathVariable(value = "type") String type,
			@PathVariable(value = "projectId") long projectId,
			@PathVariable(value = "operation") String operation
			) {
		ModelAndView mav = new ModelAndView();

		//String dpcUri = DesignPatternComponentServiceImpl
		//		.toDesignPatternComponentUri(type, uri);
		DesignPatternComponent component = designPatternComponentService.getDesignPatternCommponentByType(
				projectId, DesignPatternType.valueOf(type.toUpperCase()));
		DesignPatternInstanceBean dpiBean = designPatternComponentService
				.getDesignPatternInstanceBean(component.getUri());

		mav.addObject("dpiName", dpiBean.getName());
		mav.addObject("dpcUri", component.getUri());
		Project project = projectService.getProjectById(projectId);
		mav.addObject("project", project);
		
		List<Project> projects = projectService.getProjectList();
		mav.addObject("projects", projects.iterator());
		
		//if ("edit".equals(operation)){
			mav.addObject("isEdit", Boolean.TRUE.toString());
		//}

		switch (DesignPatternType.valueOf(type.toUpperCase())) {
		case BUS:
			List<EntityZone> entityZones = entityZoneService.getEntityZoneByProject(projectId);
			mav.addObject("entityZones", entityZones);
			
			List<BusZone> busZones = busZoneService.getBusZoneByProject(projectId);
			mav.addObject("busZones", busZones);
			
			List<DomainEntity> domainEntities = domainEntityService
					.getAllDomainEntity();

			mav.addObject("data_components", domainEntities);

			// List<AvionicsEquipment> avionicsEquipments=
			// avionicsEquipmentService.getAllAvionicsEquipmentList();
			// mav.addObject("equipments", avionicsEquipments);
			// EquipmentCategory equipmentCategory =
			// equipmentCategoryService.getEquipmentCategoryByType("bus");
			// List<AvionicsEquipment> busList =
			// avionicsEquipmentService.getAvionicsEquipmentByEquipmentCategory(equipmentCategory);
			AADLModel model = project.getModel();
			List<AvionicsEquipment> equipmentList = null;
			if (model != null){
				String modelPath = project.getModel().getXmlPath();
				// File file = new File(Const.ABSOLUTE_GENERATE_PATH + modelPath);
				File file = new File(FileUtil.getRootPath() + "generate/"
						+ modelPath);
				equipmentList = aadlParser.parseAADLToEquipmentList(file);
				List<AvionicsEquipment> busList = new ArrayList<AvionicsEquipment>();
				List<AvionicsEquipment> outterEquipmentList = new ArrayList<AvionicsEquipment>();
				for (AvionicsEquipment equipment : equipmentList) {
					if (equipment.getEquiptype().equals(
							AvionicsEquipment.EQUIPMENT_TYPE_BUS)) {
						busList.add(equipment);
					} else if (equipment.getEquiptype().equals(
							AvionicsEquipment.EQUIPMENT_TYPE_OUTTER_DEVICE)) {
						outterEquipmentList.add(equipment);
					}
				}
				mav.addObject("buses", busList);
				mav.addObject("outterEquipments", outterEquipmentList);
			}
		
			//List<AvionicsEquipment> equipmentList = new ArrayList<AvionicsEquipment>();
			
			

			//List<InterfaceMethod> interfaceMethods = interfaceMethodService
			//		.getAllInterfaceMethod();
			//mav.addObject("interfaceMethods", interfaceMethods);
			
			List<MethodComponentLink> methodComponentLinks_bus = methodComponentTool.getComponentLinksByInterfaceType(
					ComponentInterface.INTERFACE_TYPE_BUS_COM);
			mav.addObject("methodComponentLinks", methodComponentLinks_bus);
			

			List<Property> properties = dpiBean.getPropertyByName("equipment");
			List<AvionicsEquipment> existEquipments = new ArrayList<AvionicsEquipment>();
			for (Property p : properties) {
				AvionicsEquipment aEquipment = avionicsEquipmentService
						.getAvionicsEquipmentByUri(p.getValue());
				if (aEquipment != null)
					existEquipments.add(aEquipment);
			}
			mav.addObject("exist_equipments", existEquipments);
			mav.setViewName("editBusDesignPatternComponent");
			return mav;
		case DISPLAY:
			List<DomainEntity> dDomainEntities = domainEntityService
					.getAllDomainEntity();
			mav.addObject("data_components", dDomainEntities);
			mav.addObject("exist_pages", dpiBean.getInstances());
			mav.addObject("positions", positionService.getPositionList());
			mav.addObject("variables", variableService.getValidByProject(projectId));
			logger.info(variableService.getValidByProject(projectId).size());
			
			List<DisplayZone> displayZones = displayZoneService.getDisplayZoneByProject(projectId);
			mav.addObject("displayZones", displayZones);
			for (DisplayZone displayZone : displayZones){
				DomainEntity entity = domainEntityService.getDomainEntityByUri(displayZone.getEntityUri());
				if (entity!=null){
					displayZone.setEntityUri(entity.getName());
				}
			}
			
			List<DomainEntity> domainEntities2 = domainEntityService
					.getAllDomainEntity();
			mav.addObject("domainEntitys", domainEntities2);
			
			List<MethodComponentLink> methodComponentLinks_display = methodComponentTool.getComponentLinksByInterfaceType(
					ComponentInterface.INTERFACE_TYPE_INFO);
			mav.addObject("methodComponentLinks", methodComponentLinks_display);
			
			mav.setViewName("editDisplayDesignPatternComponent");
			return mav;
		case CONTROL:
			// List<InterfaceMethod> cInterfaceMethods =
			// interfaceMethodService.getAllInterfaceMethod();
			// mav.addObject("control_response_functions", cInterfaceMethods);

			List<MethodComponentLink> methodComponentLinks_control = methodComponentTool.getComponentLinksByInterfaceType(
					ComponentInterface.INTERFACE_TYPE_CONTROL_RESPONSE);
			mav.addObject("methodComponentLinks", methodComponentLinks_control);

			List<MethodComponentLink> methodComponentLinks_other = methodComponentTool.getComponentLinksByInterfaceType(
					ComponentInterface.INTERFACE_TYPE_ELSE);
			mav.addObject("otherMethodComponentLinks", methodComponentLinks_other);
			

			mav.setViewName("editControlDesignPatternComponent");
			mav.addObject("buttons", buttonService.getButtonByProject(project.getId()));

			DesignPatternComponent dpComponent = designPatternComponentService
					.getDesignPatternCommponentByType(projectId,
							DesignPatternType.DISPLAY);
			DesignPatternInstanceBean controlDpiBean = new DesignPatternInstanceBean(
					DesignPatternType.DISPLAY, dpComponent.getXmlPath());
			mav.addObject("exist_pages", controlDpiBean.getInstances());

			List<Map<String, Property>> controlMappings = dpiBean
					.getInstances();
			for (Map<String, Property> mapping : controlMappings) {
				Property pButton = mapping.get("button");
				pButton.setValue(buttonService.getButtonById(
						Long.parseLong(pButton.getValue())).getName());
				Property pType = mapping.get("type");
				if (pType.getValue().equals("function")) {
					Property pFunction = mapping.get("control_function");
					// [0] is interfaceMethod id, [1] is methodComponent uri
					String[] link = pFunction.getValue().split("=");
					String methodSigniture = interfaceMethodService
							.getInterfaceMethodById(Long.parseLong(link[0]))
							.getMethodSigniture();
					logger.info("ID:" + link[0]);
					String methodComponentName = methodComponentService
							.getMethodComponentByUri(link[1]).getName();
					logger.info("URI:" + link[1]);
					pFunction.setValue(methodSigniture + "--"
							+ methodComponentName);
				}
			}
			mav.addObject("controlMappings", controlMappings);

			return mav;
		case IO:
			mav.setViewName("editIODesignPatternComponent");
			// List<AvionicsEquipment> avionicsEquipments =
			// avionicsEquipmentService.getAllAvionicsEquipmentList();
			// mav.addObject("equipments", avionicsEquipments);

			/*String xmlPath = project.getModel().getXmlPath();
			File xmlFile = new File(FileUtil.getRootPath() + "generate/"
					+ xmlPath);

			List<AvionicsEquipment> iEquipmentList = aadlParser
					.parseAADLToEquipmentList(xmlFile);
			*/
			List<InterfaceMethod> interfaceMethods_io = interfaceMethodService
					.getAllInterfaceMethod();
			mav.addObject("interfaceMethods", interfaceMethods_io);
			
			List<MethodComponentLink> methodComponentLinks_io = methodComponentTool
					.getComponentLinks();
			mav.addObject("methodComponentLinks", methodComponentLinks_io);
			
			List<AvionicsEquipment> innerDevices = avionicsEquipmentService
					.getAvionicsEquipmentByType(AvionicsEquipment.EQUIPMENT_TYPE_INNER_DEVICE);
			
			
			mav.addObject("equipments", innerDevices);

			
			List<AvionicsEquipment> iInnerBusList = avionicsEquipmentService
					.getAvionicsEquipmentByType(AvionicsEquipment.EQUIPMENT_TYPE_BUS);
//			List<AvionicsEquipment> iInnerBusList = new ArrayList<AvionicsEquipment>();
//			for (AvionicsEquipment equipment : iEquipmentList) {
//				if (equipment.getEquiptype().equals(
//						AvionicsEquipment.EQUIPMENT_TYPE_BUS)) {
//					iInnerBusList.add(equipment);
//				}
//			}
			mav.addObject("inner_buses", iInnerBusList);

			List<Property> iProperties = dpiBean.getPropertyByName("equipment");
			List<AvionicsEquipment> iExistEquipments = new ArrayList<AvionicsEquipment>();
			for (Property p : iProperties) {
				AvionicsEquipment aEquipment = avionicsEquipmentService
						.getAvionicsEquipmentByUri(p.getValue());
				if (aEquipment != null)
					iExistEquipments.add(aEquipment);
			}
			mav.addObject("exist_equipments", iExistEquipments);

			return mav;

		}
		return mav;
	}
	
	@RequestMapping(value = "/common", method = RequestMethod.GET)
	public void downloadCommonCode(HttpServletResponse response) throws IOException {
		String commonPathile = DesignPatternComponentController.class.getResource("/systemdata/initial/common/common.zip").getPath();
		File zipFile = new File(commonPathile);
		InputStream is = new FileInputStream(zipFile);
		response.setContentType("application/octet-stream");
		response.setContentLength((int) zipFile.length());
		String headerKey = "Content-Disposition";
		String headerValue = String.format("attachment;filename=\"%s\"",
				zipFile.getName());
		response.setHeader(headerKey, headerValue);
		IOUtils.copy(is, response.getOutputStream());
		response.flushBuffer();
	}
}
